package com.lsh.payment.core.service.notify;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lsh.payment.core.constant.BusinessConstant;
import com.lsh.payment.core.dao.notify.PayNotifyTaskDao;
import com.lsh.payment.core.model.notify.PayNotifyRequest;
import com.lsh.payment.core.model.notify.PayNotifyTask;
import com.lsh.payment.core.model.payenum.PayChannel;
import com.lsh.payment.core.model.payenum.PayType;
import com.lsh.payment.core.model.payenum.TradeType;
import com.lsh.payment.core.model.payment.PayDeal;
import com.lsh.payment.core.service.payment.impl.PayDealService;
import com.lsh.payment.core.util.HttpClientUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Project Name: lsh-payment
 *
 * @author peter
 * Date: 16/11/7
 * 北京链商电子商务有限公司
 * Package com.lsh.payment.core.service.notifyTms
 * desc:
 */
@Service
public class BusinessNotifyService {

    private static Logger logger = LoggerFactory.getLogger(BusinessNotifyService.class);

    private static Map<Integer, Integer> strategyMap;

    @Autowired
    private PayNotifyTaskDao payNotifyTaskDao;

    @Autowired
    private PayDealService payDealService;


    static {
        strategyMap = new HashMap<>();

        strategyMap.put(TradeType.ALLINWXSM.getCode(), TradeType.QFWXSM.getCode());
        strategyMap.put(TradeType.ALLINALISM.getCode(), TradeType.QFALISM.getCode());
        strategyMap.put(TradeType.CMWXSM.getCode(), TradeType.QFWXSM.getCode());
        strategyMap.put(TradeType.CMALISM.getCode(), TradeType.QFALISM.getCode());

        strategyMap.put(TradeType.ALLINWXBSM.getCode(), TradeType.QFWXSM.getCode());
        strategyMap.put(TradeType.ALLINALIBSM.getCode(), TradeType.QFALISM.getCode());
    }

    /**
     * 定时任务调用(通知支付结果)
     *
     * @param payNotifyTask 定时任务项
     * @return int
     */
    public int dealNotify(PayNotifyTask payNotifyTask) {

        if (payNotifyTask == null) {
            return 0;
        }

        payNotifyTask.setNotifyTimes(payNotifyTask.getNotifyTimes() + 1);
        PayDeal payDeal = payDealService.queryPayDealByPayPaymentNo(payNotifyTask.getPayPaymentNo());
        if (payDeal != null) {
            payNotifyTask.setTraceModule(payDeal.getTradeModule());
        }

        if (this.sendNotify(payNotifyTask)) {
            payNotifyTask.setStatus(BusinessConstant.TMS_TASK_STATUS_SUCCESS);
        } else {
            if (payNotifyTask.getNotifyTimes() >= BusinessConstant.TMS_MAX_TIMES && payNotifyTask.getStatus().equals(BusinessConstant.TMS_TASK_STATUS_NEW)) {
                payNotifyTask.setStatus(BusinessConstant.TMS_TASK_STATUS_FAIL);
            }
        }

        return payNotifyTaskDao.updateByPrimaryKeySelective(payNotifyTask);
    }

    /**
     * 同步调用(通知支付结果)
     *
     * @param payDeal 支付记录
     */
    public void dealNotify(PayDeal payDeal) {

        String prefix = payDeal.getPayPaymentNo() + "-【回调业务方】";
        logger.info("{} start", prefix);

        TradeType tradeType = TradeType.paseTradeTypeByCode(payDeal.getTradeType());
        Integer method = tradeType.getMethod();
        logger.info("【{}】  method is【{}】", prefix, method);
        if (method == 0) {
            return;
        }

        PayNotifyTask payNotifyTask = new PayNotifyTask();
        payNotifyTask.setTradeId(payDeal.getTradeId());
        payNotifyTask.setMethod(method);
        payNotifyTask.setNotifyTimes(1);
        payNotifyTask.setReceiveAmount(payDeal.getRequestAmount());
        payNotifyTask.setLshNotifyUrl(payDeal.getLshNotifyUrl());
        payNotifyTask.setPayPaymentNo(payDeal.getPayPaymentNo());
        payNotifyTask.setTraceModule(payDeal.getTradeModule());
        payNotifyTask.setVenderId(payDeal.getVenderId());

        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        if (!this.sendNotify(payNotifyTask)) {
            payNotifyTaskDao.insertSelective(payNotifyTask);
        }
        logger.info("【真实通知业务方支付结果时间】 [" + stopWatch.getTime() + "] 毫秒, NotifyUrl is [" + payNotifyTask.getLshNotifyUrl() + "]");
        stopWatch.stop();
    }


    /**
     * 发送通知
     *
     * @param payNotifyTask 通知业务方
     * @return boolean         返回结果
     */
    private boolean sendNotify(PayNotifyTask payNotifyTask) {
        String prefix = payNotifyTask.getPayPaymentNo() + "-【回调业务方】[sendNotify] ";
        logger.info("【{}】 start", prefix);

        boolean notifySuccessFlag = false;
        int type = payNotifyTask.getMethod();
        // TODO 优化
        if (type >= TradeType.ALLINWXSM.getCode()) {
            type = strategyMap.get(type);
        }
        try {

            PayDeal payDeal = payDealService.queryPayDealByPayPaymentNo(payNotifyTask.getPayPaymentNo());
            if (payDeal == null) {
                logger.info("【{}】 payDeal 支付记录不存在", prefix);
                return false;
            }

            Integer payType = payDeal.getPayType();
            String willCode = "0";
            String pOrderCode = "0";
            List<String> togetherTrades = new ArrayList<>();
            String tradeId = payNotifyTask.getTradeId();
            if (PayType.TOGETHER_PAY.getCode() == payType) {
                JSONObject ext = JSON.parseObject(payDeal.getExt());
                JSONObject dealExt = ext.getJSONObject("ext");
                willCode = dealExt.getString("will_code");
                pOrderCode = dealExt.getString("p_order_code");

                JSONArray array = dealExt.getJSONArray("together_trades");
                togetherTrades = JSONObject.parseArray(array.toJSONString(), String.class);
                if (StringUtils.isBlank(willCode)) {
                    String[] willOrder = tradeId.split("_");
                    if (willOrder.length == 2) {
                        willCode = willOrder[0];
                        pOrderCode = willOrder[1];
                    }
                }
            }
            //支付渠道
            PayChannel payChannel = PayChannel.getPayChannel(payDeal.getPayChannel());
            if (payChannel == null) {
                logger.info("【{}】 payChannel 支付渠道不存在", prefix);
                return false;
            }

            PayNotifyRequest notifyRequest = new PayNotifyRequest()
                    .setTrade_id(payNotifyTask.getTradeId())
                    .setWill_code(willCode)
                    .setP_order_code(pOrderCode)
                    .setPay_channel(payChannel.getCode())
                    .setChannel_type(type)
                    .setPayment_amount(payNotifyTask.getReceiveAmount())
                    .setPay_payment_no(payNotifyTask.getPayPaymentNo())
                    .setPay_code("SUCCESS")
                    .setTrade_module(payNotifyTask.getTraceModule())
                    .setVenderId(payNotifyTask.getVenderId())
                    .setTogether_trades(togetherTrades);

            String notifyRequestJson = JSON.toJSONString(notifyRequest);
            logger.info("【{}】【JOP 通知业务方】参数 {} : ", prefix, notifyRequestJson);
            Map<String, String> headMap = new HashMap<>();
            headMap.put("venderId", payNotifyTask.getVenderId() + "");
            String notifyResponse = HttpClientUtils.doPostBody(payNotifyTask.getLshNotifyUrl(), notifyRequestJson, headMap);
            logger.info("【{}】【JOP 通知业务方】结果 {} : ", prefix, notifyResponse);
            String returnCode = null;
            if (StringUtils.isNotBlank(notifyResponse)) {
                JSONObject notifyResponseJson = JSON.parseObject(notifyResponse);
                if (notifyResponseJson != null && notifyResponseJson.getJSONObject(BusinessConstant.NOTIFY_RESPONSE_CONTENT) != null) {
                    returnCode = notifyResponseJson.getJSONObject(BusinessConstant.NOTIFY_RESPONSE_CONTENT).getString(BusinessConstant.NOTIFY_RESPONSE_CONTENT_RETURN_CODE);
                }
            }

            if (StringUtils.isNotBlank(returnCode) && returnCode.equals(BusinessConstant.OPERATE_SUCCESS_STRING)) {
                notifySuccessFlag = true;
            } else {
                logger.info("【{}】【JOP 通知业务方】失败 ", prefix);
            }
        } catch (Exception e) {
            logger.error("【" + prefix + "】【JOP 通知业务方】失败 ", e);
        }

        return notifySuccessFlag;
    }

}
